package com.kqb.common.redis.utils;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author 杉果树皮
 * @date 2025/3/31 13:31
 * @description: 二次封装redis命令
 */
@Component
public class RedisUtils {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;


    /**
     * @param key
     * @param value
     */
    public void set(String key, String value) {
        stringRedisTemplate.opsForValue().set(key, value);
    }

    /**
     * @param key
     * @param value
     * @param time
     */
    public void set(String key, String value, long time) {
        stringRedisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
    }

    /**
     * 如果不存在添加
     *
     * @param key
     * @param value
     */
    public Boolean setNx(String key, String value) {
        return stringRedisTemplate.opsForValue().setIfAbsent(key, value);
    }

    /**
     * 如果不存在加入
     *
     * @param key
     * @param value
     * @param time  超时时间
     * @return
     */

    public Boolean setNx(String key, String value, long time) {
        return stringRedisTemplate.opsForValue().setIfAbsent(key, value, time, TimeUnit.SECONDS);
    }

    /**
     * 只允许修改
     *
     * @param key
     * @param value
     */
    public void setXx(String key, String value) {
        stringRedisTemplate.opsForValue().setIfPresent(key, value);
    }

    /**
     * key获取 的值。
     *
     * @param key
     * @return
     */
    public String get(String key) {
        return stringRedisTemplate.opsForValue().get(key);
    }

    public Double incr(String key, double delta) {
        return stringRedisTemplate.opsForValue().increment(key, delta);
    }

    /**
     * 每次递增1
     *
     * @param key
     * @return
     */
    public Long incr(String key) {
        return stringRedisTemplate.opsForValue().increment(key);
    }

    /**
     * 每次递减1
     *
     * @param key
     * @return
     */
    public Long decr(String key) {
        return stringRedisTemplate.opsForValue().decrement(key);
    }

    public Long decr(String key, long delta) {
        return stringRedisTemplate.opsForValue().decrement(key, delta);
    }


    //json
    public void setJson(String key, Object value, long timeout) {
        redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
    }

    /**
     * 获得json格式存入的string型
     *
     * @param key           键
     * @param typeReference bean对象泛型
     * @param <T>
     * @return
     */
    public <T> T getJson(String key, TypeReference<T> typeReference) {
        return converted(redisTemplate.opsForValue().get(key), typeReference);
    }

    // 处理泛型类型（如 new TypeReference<List<Goods>>() {}）

    public <T> T converted(Object map, TypeReference<T> typeReference) {
        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.convertValue(map, typeReference);
    }

    /**
     * 执行lua脚本
     *
     * @param script
     * @param keys
     * @param argv
     * @return
     */
    public Long lua(String script, List<String> keys, String... argv) {
        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>(script, Long.class);
        return stringRedisTemplate.execute(redisScript, keys, argv);
    }

    /**
     * 删除指定键
     *
     * @param key
     * @return
     */
    public Boolean del(String key) {
        return stringRedisTemplate.delete(key);
    }

    /**
     * 判断key是否存在
     *
     * @param key
     * @return
     */
    public Boolean exists(String key) {
        return stringRedisTemplate.hasKey(key);
    }
}
